package cn.elead.chaos.shiro.realm;

import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import cn.elead.chaos.shiro.jwt.JWTCredentialsMatcher;
import cn.elead.chaos.shiro.jwt.JWTToken;
import cn.elead.chaos.shiro.service.IShiroRealmService;
import cn.elead.chaos.sso.core.user.LoginUser;

/**
 * 自定义身份认证 基于HMAC（ 散列消息认证码）的控制域
 */

public class JWTShiroRealm extends AuthorizingRealm {

	protected IShiroRealmService shiroRealmService;

	protected HttpServletRequest request;

	public JWTShiroRealm(IShiroRealmService shiroRealmService, HttpServletRequest request) {
		this.shiroRealmService = shiroRealmService;
		this.request = request;
		this.setCredentialsMatcher(new JWTCredentialsMatcher());
	}

	@Override
	public boolean supports(AuthenticationToken token) {
		return token instanceof JWTToken;
	}

	/**
	 * 认证信息.(身份验证) : Authentication 是用来验证用户身份 默认使用此方法进行用户名正确与否验证，错误抛出异常即可。
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		JWTToken jwtToken = (JWTToken) authcToken;
		String token = jwtToken.getToken();

		LoginUser user = shiroRealmService.getUser(token);
		if (user == null)
			throw new AuthenticationException("token过期，请重新登录");

		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user, "123456", "jwtRealm");

		return authenticationInfo;
	}

	/**
	 * 授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		String userId = request.getAttribute("login_user_id").toString();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		// 角色列表
		Set<String> roles = shiroRealmService.selectRoleKeys(userId);
		// 功能列表
		Set<String> permss = shiroRealmService.selectPermsByUserId(userId);
		// 角色加入AuthorizationInfo认证对象
		info.setRoles(roles);
		// 权限加入AuthorizationInfo认证对象
		info.setStringPermissions(permss);
		return info;
	}

	/**
	 * 清理缓存权限
	 */
	public void clearCachedAuthorizationInfo() {
		this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
	}
}
